#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <termios.h>
#include <time.h>
#include <errno.h>
#include <ctype.h>

#define JSON_RESPONSE "Content-Type: application/json;charset=UTF-8\r\n\r\n"
#define SERIAL_PORT "/dev/ttyUSB0"
#define LOCK_FILE "/tmp/zigbee_lock"

// 添加调试日志函数
void log_debug(const char *message) {
    FILE *log = fopen("/tmp/led_control_debug.log", "a");
    if (log) {
        time_t now = time(NULL);
        fprintf(log, "[%ld] %s\n", now, message);
        fclose(log);
    }
}

int init_serial();
int acquire_lock();
int release_lock();
int send_command(const char *cmd);
void urldecode(char *dst, const char *src);

int main() {
    printf(JSON_RESPONSE);
    
    log_debug("=== LED控制CGI启动 ===");
    
    char *query_string = getenv("QUERY_STRING");
    if (!query_string) {
        log_debug("错误: 缺少查询参数");
        printf("{\"status\":\"error\",\"msg\":\"缺少参数\"}");
        return 1;
    }
    
    log_debug(query_string);
    
    char action[32] = {0};
    char value[32] = {0};
    
    char decoded_query[256] = {0};
    urldecode(decoded_query, query_string);
    
    char *token = strtok(decoded_query, "&");
    while (token) {
        char *eq = strchr(token, '=');
        if (eq) {
            *eq = '\0';
            char *name = token;
            char *val = eq + 1;
            
            if (strcmp(name, "action") == 0) strncpy(action, val, 31);
            else if (strcmp(name, "value") == 0) strncpy(value, val, 31);
        }
        token = strtok(NULL, "&");
    }
    
    // 记录接收到的参数
    char log_msg[256];
    snprintf(log_msg, sizeof(log_msg), "解析参数: action=%s, value=%s", action, value);
    log_debug(log_msg);
    
    if (strlen(action) == 0) {
        log_debug("错误: 缺少action参数");
        printf("{\"status\":\"error\",\"msg\":\"缺少action参数\"}");
        return 1;
    }
    
    char cmd[128];
    
    if (strcmp(action, "on") == 0) {
        // 新格式：开启LED，亮度默认50
        snprintf(cmd, sizeof(cmd), "{\"source\":\"rk3568\",\"device\":\"led\",\"data\":{\"id\":1,\"open\":1,\"bright\":50}}");
        log_debug("准备发送LED开启命令");
    }
    else if (strcmp(action, "off") == 0) {
        // 新格式：关闭LED，亮度设为0
        snprintf(cmd, sizeof(cmd), "{\"source\":\"rk3568\",\"device\":\"led\",\"data\":{\"id\":1,\"open\":0,\"bright\":0}}");
        log_debug("准备发送LED关闭命令");
    }
    else if (strcmp(action, "brightness") == 0 && strlen(value) > 0) {
        int brightness = atoi(value);
        if (brightness < 0) brightness = 0;
        if (brightness > 100) brightness = 100;
        
        // 新格式：设置亮度，保持开启状态
        snprintf(cmd, sizeof(cmd), "{\"source\":\"rk3568\",\"device\":\"led\",\"data\":{\"id\":1,\"open\":1,\"bright\":%d}}", brightness);
        log_debug("准备发送LED亮度调节命令");
    }
    else {
        log_debug("错误: 不支持的LED操作");
        printf("{\"status\":\"error\",\"msg\":\"不支持的LED操作\"}");
        return 1;
    }
    
    // 记录最终要发送的JSON
    char final_cmd_log[256];
    snprintf(final_cmd_log, sizeof(final_cmd_log), "最终JSON命令: %s", cmd);
    log_debug(final_cmd_log);
    
    if (send_command(cmd) == 0) {
        log_debug("命令发送成功");
        if (strcmp(action, "brightness") == 0) {
            printf("{\"status\":\"success\",\"msg\":\"亮度设置成功\",\"value\":%s}", value);
        } else {
            const char *msg = (strcmp(action, "on") == 0) ? "LED已开启" : "LED已关闭";
            printf("{\"status\":\"success\",\"msg\":\"%s\"}", msg);
        }
    } else {
        log_debug("命令发送失败");
        printf("{\"status\":\"error\",\"msg\":\"操作失败\"}");
    }
    
    log_debug("=== LED控制CGI结束 ===");
    return 0;
}

// 以下函数保持不变...
int init_serial() {
    log_debug("初始化串口...");
    
    int fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
        char err_msg[100];
        snprintf(err_msg, sizeof(err_msg), "打开串口失败: %s", strerror(errno));
        log_debug(err_msg);
        return -1;
    }
    
    struct termios tty;
    if (tcgetattr(fd, &tty) != 0) {
        log_debug("获取串口属性失败");
        close(fd);
        return -1;
    }
    
    cfsetospeed(&tty, B9600);
    cfsetispeed(&tty, B9600);
    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
    tty.c_iflag &= ~IGNBRK;
    tty.c_lflag = 0;
    tty.c_oflag = 0;
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 5;
    tty.c_iflag &= ~(IXON | IXOFF | IXANY);
    tty.c_cflag |= (CLOCAL | CREAD);
    tty.c_cflag &= ~(PARENB | PARODD);
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;
    
    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        log_debug("设置串口属性失败");
        close(fd);
        return -1;
    }
    
    log_debug("串口初始化成功");
    return fd;
}

int acquire_lock() {
    log_debug("获取文件锁...");
    int lock_fd = open(LOCK_FILE, O_CREAT | O_RDWR, 0666);
    if (lock_fd < 0) {
        log_debug("创建锁文件失败");
        return -1;
    }
    if (flock(lock_fd, LOCK_EX | LOCK_NB) != 0) {
        log_debug("串口被其他进程占用");
        close(lock_fd);
        return -1;
    }
    log_debug("文件锁获取成功");
    return lock_fd;
}

int release_lock() {
    log_debug("释放文件锁...");
    int lock_fd = open(LOCK_FILE, O_RDWR);
    if (lock_fd < 0) return -1;
    flock(lock_fd, LOCK_UN);
    close(lock_fd);
    log_debug("文件锁释放成功");
    return 0;
}

int send_command(const char *cmd) {
    log_debug("开始发送命令到串口...");
    
    int lock_fd = acquire_lock();
    if (lock_fd < 0) {
        log_debug("获取锁失败");
        return -1;
    }
    
    int serial_fd = init_serial();
    if (serial_fd < 0) {
        log_debug("串口初始化失败");
        release_lock();
        return -1;
    }
    
    // 记录发送的命令（包含换行符）
    char full_cmd[256];
    snprintf(full_cmd, sizeof(full_cmd), "%s\n", cmd);
    
    char log_cmd[300];
    snprintf(log_cmd, sizeof(log_cmd), "实际发送的数据: %s", full_cmd);
    log_debug(log_cmd);
    
    ssize_t written = write(serial_fd, full_cmd, strlen(full_cmd));
    
    if (written != (ssize_t)strlen(full_cmd)) {
        log_debug("命令发送不完整");
        close(serial_fd);
        release_lock();
        return -1;
    }
    
    tcdrain(serial_fd);
    log_debug("命令发送完成");
    
    close(serial_fd);
    release_lock();
    log_debug("命令处理完成");
    return 0;
}

void urldecode(char *dst, const char *src) {
    char a, b;
    while (*src) {
        if ((*src == '%') && (a = src[1]) && (b = src[2]) && isxdigit(a) && isxdigit(b)) {
            if (a >= 'a') a -= 'a'-'A';
            if (a >= 'A') a -= ('A' - 10);
            else a -= '0';
            if (b >= 'a') b -= 'a'-'A';
            if (b >= 'A') b -= ('A' - 10);
            else b -= '0';
            *dst++ = 16*a+b;
            src += 3;
        } else if (*src == '+') {
            *dst++ = ' ';
            src++;
        } else {
            *dst++ = *src++;
        }
    }
    *dst = '\0';
}
